package com.horsen.service.edu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.horsen.common.util.R;
import com.horsen.service.base.model.VO.WebCourseOrderVO;
import com.horsen.service.edu.mapper.*;
import com.horsen.service.edu.model.*;
import com.horsen.service.edu.model.DTO.CourseInsertDTO;
import com.horsen.service.edu.model.DTO.CourseQueryDTO;
import com.horsen.service.edu.model.DTO.WebCourseQueryDTO;
import com.horsen.service.edu.model.VO.*;
import com.horsen.service.edu.service.CourseService;
import com.horsen.service.edu.service.feign.OSSFileService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 * 课程 服务实现类
 * </p>
 *
 * @author Horsen
 * @since 2021-04-06
 */
@Slf4j
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements CourseService {

    @Autowired
    private VideoMapper videoMapper;
    @Autowired
    private ChapterMapper chapterMapper;
    @Autowired
    private CourseStarMapper courseStarMapper;
    @Autowired
    private CourseDescriptionMapper courseDescriptionMapper;
    @Autowired
    private OSSFileService ossFileService;

    /**
     * 分页查询
     *
     * @param page           当前页码
     * @param limit          每页记录数
     * @param courseQueryDTO 课程查询DTO
     * @return IPage类实例
     */
    @Override
    public IPage<CourseListVO> pageSelect(Long page, Long limit, CourseQueryDTO courseQueryDTO) {
        // 分页参数
        Page<CourseListVO> pageParam = new Page<>(page, limit);
        // 查询结果
        List<CourseListVO> records;
        QueryWrapper<Course> queryWrapper = Wrappers.query();
        queryWrapper.eq("c.is_deleted", 0);
        queryWrapper.orderByDesc("c.gmt_create");
        if (courseQueryDTO != null) {
            String title = courseQueryDTO.getTitle();
            String teacherId = courseQueryDTO.getTeacherId();
            String subjectParentId = courseQueryDTO.getSubjectParentId();
            String subjectId = courseQueryDTO.getSubjectId();

            if (!StringUtils.isEmpty(title)) {
                queryWrapper.like("c.title", title);
            }
            if (!StringUtils.isEmpty(teacherId)) {
                queryWrapper.eq("c.teacher_id", teacherId);
            }
            if (!StringUtils.isEmpty(subjectParentId)) {
                queryWrapper.eq("c.subject_parent_id", subjectParentId);
            }
            if (!StringUtils.isEmpty(subjectId)) {
                queryWrapper.eq("c.subject_id", subjectId);
            }
        }
        records = baseMapper.selectPageWithMultiTable(pageParam, queryWrapper);
        pageParam.setRecords(records);
        return pageParam;
    }

    /**
     * 新增一个课程
     *
     * @param courseInsertDTO 课程新增DTO
     * @return 课程ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String insert(CourseInsertDTO courseInsertDTO) {
        // 保存课程基本信息
        Course course = new Course();
        BeanUtils.copyProperties(courseInsertDTO, course);
        course.setStatus(Course.COURSE_STATE_DRAFT);
        baseMapper.insert(course);
        // 保存课程介绍
        courseDescriptionMapper.insert(new CourseDescription()
                .setDescription(courseInsertDTO.getDescription())
                .setId(course.getId()));
        // 返回课程ID
        return course.getId();
    }

    /**
     * 根据ID获取一个CourseInfoVO
     *
     * @param id 课程ID
     * @return CourseInfoVO
     */
    @Override
    public CourseInfoVO queryInfoById(String id) {
        Course course = baseMapper.selectById(id);
        if (course == null) {
            return null;
        }
        CourseInfoVO courseInfoVO = new CourseInfoVO();
        BeanUtils.copyProperties(course, courseInfoVO);
        courseInfoVO.setDescription(courseDescriptionMapper.selectById(id).getDescription());
        return courseInfoVO;
    }

    /**
     * 修改一个课程
     *
     * @param courseInfoVO 课程信息VO
     * @return 是否修改成功
     */
    @Override
    public Boolean updateById(CourseInfoVO courseInfoVO) {
        // 保存课程基本信息
        Course course = new Course();
        BeanUtils.copyProperties(courseInfoVO, course);
        int i = baseMapper.updateById(course);
        // 保存课程介绍
        int j = courseDescriptionMapper.updateById(new CourseDescription()
                .setDescription(courseInfoVO.getDescription())
                .setId(course.getId()));
        return i != 0 && j != 0;
    }

    /**
     * 根据课程ID删除封面
     *
     * @param id 课程ID
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteCoverById(String id) {
        Course course = baseMapper.selectById(id);
        // 确保课程存在
        if (course != null) {
            String url = course.getCover();
            // 确保课程有封面
            if (!StringUtils.isEmpty(url)) {
                R result = ossFileService.delete(url);
                // 返回成功结果
                return result.getSuccess();
            }
        }
        return false;
    }

    /**
     * 根据课程ID删除视频
     *
     * @param id 课程ID
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteVideoById(String id) {
        // TODO: 从VOD删除视频
        return false;
    }

    /**
     * 根据ID删除课程
     *
     * @param id 课程ID
     * @return 删除是否成功
     */
    @Override
    public Boolean deleteById(String id) {
        LambdaUpdateWrapper<Course> courseUpdateWrapper = Wrappers.lambdaUpdate();
        LambdaQueryWrapper<CourseStar> courseStarQueryWrapper = Wrappers.lambdaQuery();
        LambdaQueryWrapper<Video> videoQueryWrapper = Wrappers.lambdaQuery();
        LambdaQueryWrapper<Chapter> chapterQueryWrapper = Wrappers.lambdaQuery();
        // 设置cover字段为null
        courseUpdateWrapper.set(Course::getCover, null);
        courseUpdateWrapper.eq(Course::getId, id);
        // 删除封面
        Boolean coverResult = this.deleteCoverById(id);
        if (coverResult) {
            log.info("删除封面成功");
        } else {
            log.info("删除封面失败");
        }
        // 删除视频
        Boolean videoResult = this.deleteVideoById(id);
        if (videoResult) {
            log.info("删除视频成功");
        } else {
            log.info("删除视频失败");
        }
        // 删除收藏
        courseStarMapper.delete(courseStarQueryWrapper.eq(CourseStar::getCourseId, id));
        // 删除视频
        videoMapper.delete(videoQueryWrapper.eq(Video::getCourseId, id));
        // 删除章节
        chapterMapper.delete(chapterQueryWrapper.eq(Chapter::getCourseId, id));
        // 删除课程详情
        courseDescriptionMapper.deleteById(id);
        // 删除url字段
        this.update(courseUpdateWrapper);
        return this.removeById(id);
    }

    /**
     * 根据ID获取一个CoursePublishVO
     *
     * @param id 课程ID
     * @return CoursePublishVO
     */
    @Override
    public CoursePublishVO getPublishById(String id) {
        return baseMapper.selectPublishById(id);
    }

    /**
     * 按条件获取课程
     *
     * @param webCourseQueryDTO 课程展示VO
     * @return 课程列表
     */
    @Override
    public List<Course> queryBy(WebCourseQueryDTO webCourseQueryDTO) {
        LambdaQueryWrapper<Course> queryWrapper = Wrappers.lambdaQuery();
        // 查询已发布的课程
        queryWrapper.eq(Course::getStatus, Course.COURSE_STATE_PASS);
        if (!StringUtils.isEmpty(webCourseQueryDTO.getCourseTitle())) {
            queryWrapper.like(Course::getTitle, webCourseQueryDTO.getCourseTitle());
        }
        if (!StringUtils.isEmpty(webCourseQueryDTO.getSubjectParentId())) {
            queryWrapper.eq(Course::getSubjectParentId, webCourseQueryDTO.getSubjectParentId());
        }
        if (!StringUtils.isEmpty(webCourseQueryDTO.getSubjectId())) {
            queryWrapper.eq(Course::getSubjectId, webCourseQueryDTO.getSubjectId());
        }
        if (!StringUtils.isEmpty(webCourseQueryDTO.getBuyCountSort())) {
            queryWrapper.orderByDesc(Course::getBuyCount);
        }
        if (!StringUtils.isEmpty(webCourseQueryDTO.getGmtCreateSort())) {
            queryWrapper.orderByDesc(Course::getGmtCreate);
        }
        if (!StringUtils.isEmpty(webCourseQueryDTO.getPriceSort())) {
            if (webCourseQueryDTO.getType() == null || webCourseQueryDTO.getType() == 1) {
                // 价格从低到高
                queryWrapper.orderByAsc(Course::getPrice);
            } else {
                // 价格从高到低
                queryWrapper.orderByDesc(Course::getPrice);
            }
        }
        return baseMapper.selectList(queryWrapper);
    }

    /**
     * 根据ID获取课程信息并更新浏览量
     *
     * @param id 课程ID
     * @return WebCourseInfoVO
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public WebCourseInfoVO queryWebInfoById(String id) {
        // 更新浏览量
        Course course = baseMapper.selectById(id);
        // 判断课程是否为已发布
        if (StringUtils.equals(course.getStatus(), Course.COURSE_STATE_PASS)) {
            course.setViewCount(course.getViewCount() + 1);
            baseMapper.updateById(course);
            // 获取前台需要的课程信息
            return baseMapper.selectWebInfoById(id);
        }
        return null;
    }

    /**
     * 根据ID获取一个课程订单VO
     *
     * @param id 课程ID
     * @return 课程订单VO
     */
    @Override
    public WebCourseOrderVO getCourseOrderById(String id) {
        return baseMapper.getCourseOrderById(id);
    }

    /**
     * 根据ID增加课程销量
     *
     * @param id 课程ID
     * @return 是否修改成功
     */
    @Override
    public Boolean addBuyCount(String id) {
        Course course = baseMapper.selectById(id);
        course.setBuyCount(course.getBuyCount() + 1);
        return this.updateById(course);
    }

    /**
     * 获取课程柱状图数据
     *
     * @return 课程柱状图VO
     */
    @Override
    public Map<String, Object> getChartValue() {
        // 作为返回map
        Map<String, Object> chartValue = new HashMap<>();
        // 作为category数组
        List<String> category = new ArrayList<>();
        // 作为value数组
        List<Integer> value = new ArrayList<>();
        // 从数据库获得数据
        List<CourseChartVO> courseChartVO = baseMapper.getChartValue();
        // 拆分成两个List
        for (CourseChartVO chartVO : courseChartVO) {
            category.add(chartVO.getCategory());
            value.add(chartVO.getValue());
        }
        // 倒序
        Collections.reverse(category);
        Collections.reverse(value);
        // 保存到map中
        chartValue.put("category", category);
        chartValue.put("value", value);
        return chartValue;
    }
}
